package com.yunc.modules.gen.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.StrSpliter;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.yunc.base.properties.GenPro;
import com.yunc.base.utils.R;
import com.yunc.modules.gen.entity.dto.ColumnDTO;
import com.yunc.modules.gen.entity.dto.TableDTO;
import com.yunc.modules.gen.service.IGenService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 数据库表
 *
 * @author congcong tao
 * @date 2019/1/28 13:36
 */
@RestController
@RequestMapping("gen")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class GenController {

    private final GenPro genPro;
    private final IGenService genService;

    @GetMapping("/page")
    public R page(Page<TableDTO> page, TableDTO tableDTO){
        genService.pageInfo(page, tableDTO);
        return R.ok().put("data", page.getRecords()).put("count", page.getTotal());
    }

    @GetMapping("/getTableByName/{tableName}")
    public R getTableByName(@PathVariable String tableName){
        TableDTO tableInfo = genService.getByTableName(tableName);
        List<ColumnDTO> columnList = genService.getTableColumnsByName(tableName);
        if (CollUtil.isNotEmpty(columnList)) {
            for (ColumnDTO columnDTO : columnList) {
                columnDTO.setSearchChecked(false);
                columnDTO.setSearchType("1");
                columnDTO.setTableChecked(true);
                if (StringUtils.equals(columnDTO.getColumnName(), "creator") ||
                        StringUtils.equals(columnDTO.getColumnName(), "create_time") ||
                        StringUtils.equals(columnDTO.getColumnName(), "updater") ||
                        StringUtils.equals(columnDTO.getColumnName(), "update_time") ) {
                    columnDTO.setFormChecked(false);
                } else {
                    columnDTO.setFormChecked(true);
                }
                if (StringUtils.contains(columnDTO.getColumnName(), "time") ||
                        StringUtils.contains(columnDTO.getColumnName(), "date")) {
                    columnDTO.setType("4");
                } else {
                    columnDTO.setType("1");
                }
            }
        }
        // 默认实体类名称，驼峰
        String className = NamingStrategy.underlineToCamel(tableInfo.getTableName());
        tableInfo.setClassName(NamingStrategy.capitalFirst(className));
        // 取第一个下划线的
        String[] split = tableInfo.getTableName().split("_");
        String moduleName = split[0];
        // 输出文件夹
        String generatorOutputDir = System.getProperty("user.dir") + "/src/main/java";
        tableInfo.setOutputDir(generatorOutputDir);
        if (StringUtils.isNotEmpty(genPro.getGenAuthor())) {
            tableInfo.setAuthor(genPro.getGenAuthor());
        }
        if (StringUtils.isNotEmpty(genPro.getGenPackageInfo())) {
            tableInfo.setPackageInfo(genPro.getGenPackageInfo());
        }
        tableInfo.setModuleName(moduleName);
        return R.ok().put("tableInfo", tableInfo).put("columnList", columnList);
    }

    @GetMapping("/getTableColumnsByName/{tableName}")
    public R getTableColumnsByName(@PathVariable String tableName){
        List<ColumnDTO> columnList = genService.getTableColumnsByName(tableName);
        return R.ok().put("columnList", columnList);
    }

    @PostMapping("/generate")
    public R export(TableDTO tableInfo){
        // String projectPath = System.getProperty("user.dir");
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();
        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        // 是否覆盖
        gc.setFileOverride(false);
        gc.setOutputDir(tableInfo.getOutputDir());
        gc.setAuthor(tableInfo.getAuthor());
        gc.setOpen(false);
        // 设置时间类型为Date
        gc.setDateType(DateType.ONLY_DATE);
        // gc.setIdType(IdType.AUTO);
        // 设置类名称
        gc.setEntityName(tableInfo.getClassName());
        gc.setMapperName(tableInfo.getClassName() + "Mapper");
        gc.setServiceName("I" + tableInfo.getClassName() + "Service");
        gc.setServiceImplName(tableInfo.getClassName() + "ServiceImpl");
        gc.setControllerName(tableInfo.getClassName() + "Controller");
        mpg.setGlobalConfig(gc);
        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl(genPro.getGenUrl());
        // dsc.setSchemaName("public");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername(genPro.getGenUserName());
        dsc.setPassword(genPro.getGenPassword());
        mpg.setDataSource(dsc);
        // 包配置
        PackageConfig pc = new PackageConfig();
        pc.setModuleName(tableInfo.getModuleName());
        pc.setParent(tableInfo.getPackageInfo());
        mpg.setPackageInfo(pc);
        // 自定义配置
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                Map hashMap = new HashMap(6);
                hashMap.put("entityName", StringUtils.uncapitalize(tableInfo.getClassName()));
                // tableInfo
                String tableName = tableInfo.getTableName();
                List<String> split = StrSpliter.splitTrim(tableName, '_', true);
                hashMap.put("splitArgs", split);
                // 传入字段，是否需要上传图片，是否需要文本框等
                String columnJson = tableInfo.getColumnJson();
                List<ColumnDTO> tableList = new ArrayList<>();
                List<ColumnDTO> formList = new ArrayList<>();
                List<ColumnDTO> searchList = new ArrayList<>();
                // 是否有图片上传
                boolean imageFlag = false;
                if (StringUtils.isNotEmpty(columnJson)) {
                    List<ColumnDTO> columnDTOList = JSONObject.parseArray(columnJson, ColumnDTO.class);
                    if (CollUtil.isNotEmpty(columnDTOList)) {
                        for (ColumnDTO column : columnDTOList) {
                            column.setSqlColumnName(column.getColumnName());
                            String columnName = NamingStrategy.underlineToCamel(column.getColumnName());
                            column.setUpperCaseColumnName(StringUtils.capitalize(columnName));
                            column.setColumnName(columnName);
                            if (column.getTableChecked()) {
                                tableList.add(column);
                            }
                            if (column.getFormChecked()) {
                                formList.add(column);
                            }
                            if (column.getSearchChecked()) {
                                // 需要处理get方法及字段
                                searchList.add(column);
                            }
                            if (StringUtils.equals(column.getType(), "5")) {
                                imageFlag = true;
                            }
                        }
                    }
                }
                hashMap.put("imageFlag", imageFlag);
                hashMap.put("tableList", tableList);
                hashMap.put("formList", formList);
                hashMap.put("searchList", searchList);
                hashMap.put("tableComment", tableInfo.getTableComment());
                hashMap.put("moduleName", tableInfo.getModuleName());
                this.setMap(hashMap);
            }
        };
        // 前端模板
        String apiPath = "/gentemplates/api.js.ftl";
        String vuePath = "/gentemplates/vue-list.vue.ftl";
        // 自定义输出配置
        List<FileOutConfig> focList = new ArrayList<>();
        // api
        focList.add(new FileOutConfig(apiPath) {
            @Override
            public String outputFile(TableInfo table) {
                // 自定义输出文件名
                return genPro.getGenFrontOutputDir() + "/src/api/" + tableInfo.getModuleName() + "/" +
                           StringUtils.uncapitalize(table.getEntityName()) + ".js";
            }
        });
        // vue
        focList.add(new FileOutConfig(vuePath) {
            @Override
            public String outputFile(TableInfo table) {
                return genPro.getGenFrontOutputDir() + "/src/components/page/" + tableInfo.getModuleName() + "/" +
                        StringUtils.replace(table.getName(), "_", "-") + "-list.vue";
            }
        });
        cfg.setFileOutConfigList(focList);

        mpg.setCfg(cfg);
        // 配置模板
        TemplateConfig templateConfig = new TemplateConfig();
        // 配置自定义输出模板
        // 指定自定义模板路径，注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
        templateConfig.setEntity("gentemplates/entity2.java");
        templateConfig.setMapper("gentemplates/mapper2.java");
        templateConfig.setService("gentemplates/service2.java");
        templateConfig.setServiceImpl("gentemplates/serviceImpl2.java");
        templateConfig.setController("gentemplates/controller2.java");
        templateConfig.setXml(null);
        mpg.setTemplate(templateConfig);
        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        // strategy.setSuperEntityClass("com.baomidou.ant.common.BaseEntity");
        strategy.setEntityLombokModel(true);
        strategy.setRestControllerStyle(true);
        strategy.setInclude(tableInfo.getTableName());
        strategy.setSuperEntityColumns("id");
        strategy.setSuperMapperClass("com.yunc.base.SuperMapper");
        strategy.setControllerMappingHyphenStyle(true);
        strategy.setTablePrefix(pc.getModuleName() + "_");
        mpg.setStrategy(strategy);
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
        mpg.execute();
        return R.ok("生成成功");
    }
}
